<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Asynchronous Remote Calls</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.73.2">
<link rel="start" href="../index.html" title="RCF User Guide">
<link rel="up" href="../index.html" title="RCF User Guide">
<link rel="prev" href="AccessControl.html" title="Server-side Access Controls">
<link rel="next" href="PubSub.html" title="Publish/Subscribe">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="spirit-nav">
<a accesskey="p" href="AccessControl.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="PubSub.html"><img src="../images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="rcf_user_guide.AsyncRemoteCalls"></a><a class="link" href="AsyncRemoteCalls.html" title="Asynchronous Remote Calls"> Asynchronous Remote Calls</a>
</h2></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="AsyncRemoteCalls.html#rcf_user_guide.AsyncRemoteCalls.asynchronous_remote_call_invocation">Asynchronous
      remote call invocation</a></span></dt>
<dt><span class="section"><a href="AsyncRemoteCalls.html#rcf_user_guide.AsyncRemoteCalls.asynchronous_remote_call_dispatching">Asynchronous
      remote call dispatching</a></span></dt>
</dl></div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="rcf_user_guide.AsyncRemoteCalls.asynchronous_remote_call_invocation"></a><a class="link" href="AsyncRemoteCalls.html#rcf_user_guide.AsyncRemoteCalls.asynchronous_remote_call_invocation" title="Asynchronous remote call invocation">Asynchronous
      remote call invocation</a>
</h3></div></div></div>
<p>
        Asynchronous remote calls allow you to initate remote calls on one thread,
        and have them complete asynchronously on another thread.
      </p>
<p>
        Asynchronous remote calls are implemeted in RCF using the <code class="computeroutput"><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Future</span><span class="special">&lt;&gt;</span></code> template. Given an RCF interface:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="identifier">RCF_BEGIN</span><span class="special">(</span><span class="identifier">I_HelloWorld</span><span class="special">,</span> <span class="string">"I_HelloWorld"</span><span class="special">)</span>

    <span class="comment">// Returns number of characters printed.
</span>    <span class="identifier">RCF_METHOD_R1</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">Print</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;)</span>

<span class="identifier">RCF_END</span><span class="special">(</span><span class="identifier">I_HelloWorld</span><span class="special">)</span>
</pre>
<p>
      </p>
<p>
        , an asynchronous call is made by specifying one or more <code class="computeroutput"><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Future</span><span class="special">&lt;&gt;</span></code> arguments. For example:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="identifier">RcfClient</span><span class="special">&lt;</span><span class="identifier">I_HelloWorld</span><span class="special">&gt;</span> <span class="identifier">client</span><span class="special">((</span> <span class="identifier">RCF</span><span class="special">::</span><span class="identifier">TcpEndpoint</span><span class="special">(</span><span class="identifier">port</span><span class="special">)</span> <span class="special">));</span>
<span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Future</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">fRet</span> <span class="special">=</span> <span class="identifier">client</span><span class="special">.</span><span class="identifier">Print</span><span class="special">(</span><span class="string">"Hello World"</span><span class="special">);</span>
</pre>
<p>
      </p>
<p>
        The thread that executes this code will return immediately. It can subsequently
        poll for completion:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="comment">// Poll until remote call completes.
</span><span class="keyword">while</span> <span class="special">(!</span><span class="identifier">fRet</span><span class="special">.</span><span class="identifier">ready</span><span class="special">())</span>
<span class="special">{</span>
    <span class="identifier">RCF</span><span class="special">::</span><span class="identifier">sleepMs</span><span class="special">(</span><span class="number">500</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
      </p>
<p>
        , or it can wait for completion:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="comment">// Wait for remote call to complete.
</span><span class="identifier">fRet</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span>
</pre>
<p>
      </p>
<p>
        Once the call is complete, the return values can be recovered from the relevant
        <code class="computeroutput"><span class="identifier">Future</span><span class="special">&lt;&gt;</span></code>
        instances:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">charsPrinted</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">fRet</span><span class="special">;</span>
</pre>
<p>
      </p>
<p>
        If the call resulted in an error, the error will be thrown when the <code class="computeroutput"><span class="identifier">Future</span><span class="special">&lt;&gt;</span></code>
        instance is dereferenced, as above. Alternatively, the error can be retrieved
        by calling <code class="computeroutput"><span class="identifier">Future</span><span class="special">&lt;&gt;::</span><span class="identifier">getAsyncException</span><span class="special">()</span></code>:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">auto_ptr</span><span class="special">&lt;</span><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Exception</span><span class="special">&gt;</span> <span class="identifier">ePtr</span> <span class="special">=</span> <span class="identifier">fRet</span><span class="special">.</span><span class="identifier">getAsyncException</span><span class="special">();</span>
</pre>
<p>
      </p>
<p>
        Instead of polling or waiting, the thread that initiates an asynchronous
        remote call can provide a completion callback that will be called by the
        RCF runtime, on a background thread, when the call completes:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">shared_ptr</span><span class="special">&lt;</span> <span class="identifier">RcfClient</span><span class="special">&lt;</span><span class="identifier">I_HelloWorld</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">HelloWorldPtr</span><span class="special">;</span>
<span class="keyword">void</span> <span class="identifier">onCallCompleted</span><span class="special">(</span><span class="identifier">HelloWorldPtr</span> <span class="identifier">client</span><span class="special">,</span> <span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Future</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">fRet</span><span class="special">)</span>
<span class="special">{</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">auto_ptr</span><span class="special">&lt;</span><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Exception</span><span class="special">&gt;</span> <span class="identifier">ePtr</span> <span class="special">=</span> <span class="identifier">fRet</span><span class="special">.</span><span class="identifier">getAsyncException</span><span class="special">();</span>
    <span class="keyword">if</span> <span class="special">(</span><span class="identifier">ePtr</span><span class="special">.</span><span class="identifier">get</span><span class="special">())</span>
    <span class="special">{</span>
        <span class="comment">// Deal with any exception.
</span>        <span class="comment">// ...
</span>    <span class="special">}</span>
    <span class="keyword">else</span>
    <span class="special">{</span>
        <span class="keyword">int</span> <span class="identifier">charsPrinted</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">fRet</span><span class="special">;</span>
        <span class="comment">// ...
</span>    <span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Future</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">fRet</span><span class="special">;</span>
<span class="identifier">HelloWorldPtr</span> <span class="identifier">client</span><span class="special">(</span> <span class="keyword">new</span> <span class="identifier">RcfClient</span><span class="special">&lt;</span><span class="identifier">I_HelloWorld</span><span class="special">&gt;(</span><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">TcpEndpoint</span><span class="special">(</span><span class="identifier">port</span><span class="special">))</span> <span class="special">);</span>
<span class="identifier">fRet</span> <span class="special">=</span> <span class="identifier">client</span><span class="special">-&gt;</span><span class="identifier">Print</span><span class="special">(</span> 
    <span class="identifier">RCF</span><span class="special">::</span><span class="identifier">AsyncTwoway</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(&amp;</span><span class="identifier">onCallCompleted</span><span class="special">,</span> <span class="identifier">client</span><span class="special">,</span> <span class="identifier">fRet</span><span class="special">)),</span> 
    <span class="string">"Hello World"</span><span class="special">);</span>
</pre>
<p>
      </p>
<p>
        Notice that the <code class="computeroutput"><span class="identifier">Future</span><span class="special">&lt;&gt;</span></code>
        arguments are passed as arguments to the completion callback function. <code class="computeroutput"><span class="identifier">Future</span><span class="special">&lt;&gt;</span></code>
        objects are internally reference counted, and can be copied freely, while
        still referring to the same underlying value.
      </p>
<p>
        An asynchronous call in progress can be canceled by disconnecting the client:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="identifier">client</span><span class="special">.</span><span class="identifier">getClientStub</span><span class="special">().</span><span class="identifier">disconnect</span><span class="special">();</span>
</pre>
<p>
      </p>
<p>
        If a <code class="computeroutput"><span class="identifier">RcfClient</span></code> is destroyed
        while an asynchronous call is in progress, the call is automatically disconnected
        and any asynchronous operations are canceled.
      </p>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h3 class="title">
<a name="rcf_user_guide.AsyncRemoteCalls.asynchronous_remote_call_dispatching"></a><a class="link" href="AsyncRemoteCalls.html#rcf_user_guide.AsyncRemoteCalls.asynchronous_remote_call_dispatching" title="Asynchronous remote call dispatching">Asynchronous
      remote call dispatching</a>
</h3></div></div></div>
<p>
        On the server-side, RCF will normally dispatch a remote call on the same
        server thread that receives the remote call request from the transport. Asynchronous
        dispatching allows you to instead transfer the remote call over to other
        threads, freeing up the RCF thread to process other remote calls.
      </p>
<p>
        The <code class="computeroutput"><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">RemoteCallContext</span><span class="special">&lt;&gt;</span></code>
        class is used to capture the server-side context of a remote call. <code class="computeroutput"><span class="identifier">RemoteCallContext</span><span class="special">&lt;&gt;</span></code>
        objects can be copied into queues and stored for later execution on arbitrary
        application threads.
      </p>
<p>
        <code class="computeroutput"><span class="identifier">RemoteCallContext</span><span class="special">&lt;&gt;</span></code>
        objects are created from within the corresponding servant implemenation method.
        Here is a non-asynchronously dispatched <code class="computeroutput"><span class="identifier">Print</span><span class="special">()</span></code> method:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="identifier">RCF_BEGIN</span><span class="special">(</span><span class="identifier">I_HelloWorld</span><span class="special">,</span> <span class="string">"I_HelloWorld"</span><span class="special">)</span>

    <span class="comment">// Returns number of characters printed.
</span>    <span class="identifier">RCF_METHOD_R1</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">Print</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;)</span>

<span class="identifier">RCF_END</span><span class="special">(</span><span class="identifier">I_HelloWorld</span><span class="special">)</span>

<span class="keyword">class</span> <span class="identifier">HelloWorldImpl</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
    <span class="keyword">int</span> <span class="identifier">Print</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span> <span class="identifier">s</span><span class="special">)</span>
    <span class="special">{</span>
        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"I_HelloWorld service: "</span> <span class="special">&lt;&lt;</span> <span class="identifier">s</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
        <span class="keyword">return</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">length</span><span class="special">();</span>
    <span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
      </p>
<p>
        To instead dispatch the call asynchronously, a <code class="computeroutput"><span class="identifier">RemoteCallContext</span><span class="special">&lt;&gt;</span></code> object is created in <code class="computeroutput"><span class="identifier">Print</span><span class="special">()</span></code>,
        with template parameters corresponding to the method signature:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">HelloWorldImpl</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>

    <span class="keyword">typedef</span> <span class="identifier">RCF</span><span class="special">::</span><span class="identifier">RemoteCallContext</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&amp;&gt;</span> <span class="identifier">PrintContext</span><span class="special">;</span>

    <span class="keyword">int</span> <span class="identifier">Print</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span> <span class="identifier">s</span><span class="special">)</span>
    <span class="special">{</span>
        <span class="comment">// Capture current remote call context.
</span>        <span class="identifier">PrintContext</span> <span class="identifier">printContext</span><span class="special">(</span><span class="identifier">RCF</span><span class="special">::</span><span class="identifier">getCurrentRcfSession</span><span class="special">());</span>

        <span class="comment">// Create a new thread to dispatch the remote call.
</span>        <span class="identifier">RCF</span><span class="special">::</span><span class="identifier">ThreadPtr</span> <span class="identifier">threadPtr</span><span class="special">(</span> <span class="keyword">new</span> <span class="identifier">RCF</span><span class="special">::</span><span class="identifier">Thread</span><span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">bind</span><span class="special">(</span>
            <span class="special">&amp;</span><span class="identifier">HelloWorldImpl</span><span class="special">::</span><span class="identifier">threadFunc</span><span class="special">,</span> 
            <span class="keyword">this</span><span class="special">,</span> 
            <span class="identifier">printContext</span><span class="special">)</span> <span class="special">)</span> <span class="special">);</span>

        <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
    <span class="special">}</span>

    <span class="keyword">void</span> <span class="identifier">threadFunc</span><span class="special">(</span><span class="identifier">PrintContext</span> <span class="identifier">printContext</span><span class="special">)</span>
    <span class="special">{</span>
        <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span> <span class="identifier">s</span> <span class="special">=</span> <span class="identifier">printContext</span><span class="special">.</span><span class="identifier">parameters</span><span class="special">().</span><span class="identifier">a1</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span>
        <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"I_HelloWorld service: "</span> <span class="special">&lt;&lt;</span> <span class="identifier">s</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
        <span class="identifier">printContext</span><span class="special">.</span><span class="identifier">parameters</span><span class="special">().</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">length</span><span class="special">()</span> <span class="special">);</span>
        <span class="identifier">printContext</span><span class="special">.</span><span class="identifier">commit</span><span class="special">();</span>
    <span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
      </p>
<p>
        Once created, the <code class="computeroutput"><span class="identifier">RemoteCallContext</span><span class="special">&lt;&gt;</span></code> can be stored and copied like any
        other C++ object. When the <code class="computeroutput"><span class="identifier">Print</span><span class="special">()</span></code> function returns, RCF will not send a response
        to the client. The response will only be sent when <code class="computeroutput"><span class="identifier">RemoteCallContext</span><span class="special">&lt;&gt;::</span><span class="identifier">commit</span><span class="special">()</span></code> is called.
      </p>
<p>
        <code class="computeroutput"><span class="identifier">RemoteCallContext</span><span class="special">::</span><span class="identifier">parameters</span><span class="special">()</span></code>
        provides access to all the parameters of the remote call, including the return
        value. We can access in parameters:
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span> <span class="identifier">s</span> <span class="special">=</span> <span class="identifier">printContext</span><span class="special">.</span><span class="identifier">parameters</span><span class="special">().</span><span class="identifier">a1</span><span class="special">.</span><span class="identifier">get</span><span class="special">();</span>
</pre>
<p>
      </p>
<p>
        , and set out parameters (in this case the return value):
      </p>
<p>
        
</p>
<pre class="programlisting"><span class="identifier">printContext</span><span class="special">.</span><span class="identifier">parameters</span><span class="special">().</span><span class="identifier">r</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">length</span><span class="special">()</span> <span class="special">);</span>
</pre>
<p>
      </p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2005 - 2014 Delta V Software</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="AccessControl.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="PubSub.html"><img src="../images/next.png" alt="Next"></a>
</div>
</body>
</html>
